package src.ee.ioc.smaug.ui.evolver;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
import java.io.File;
import java.util.logging.Level;

import javax.swing.JFileChooser;

import javax.swing.JEditorPane;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import src.ee.ioc.smaug.parser.ParameterXMLWriter;
import src.ee.ioc.smaug.world.Enviroment;
import src.ee.ioc.smaug.world.evolution.*;
import src.ee.ioc.smaug.ui.*;

public class TrParameter extends JPanel implements TreeSelectionListener,
        ActionListener {
    private JTree tree;

    final JPopupMenu menu = new JPopupMenu();

    private static String lineStyle = "none";

    public TrParameter() {
        super(new GridLayout(1, 0));

        // Create the nodes.
        DefaultMutableTreeNode top = new DefaultMutableTreeNode("Parameters");
        createNodes(top);

        // Create a tree that allows one selection at a time.
        tree = new JTree(top);
        tree.getSelectionModel().setSelectionMode(
                TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.addMouseListener(new DCMouseListener());
        // Listen for when the selection changes.
        tree.addTreeSelectionListener(this);
        int i = 0;
        while (i < tree.getRowCount()) {
            tree.expandRow(i);
            i++;
        }

        tree.putClientProperty("JTree.lineStyle", lineStyle);

        // Create the scroll pane and add the tree to it.
        JScrollPane treeView = new JScrollPane(tree);

        Dimension minimumSize = new Dimension(100, 50);
        treeView.setMinimumSize(minimumSize);

        add(treeView);

        // Create pop up menu

        JMenuItem menuItem = new JMenuItem("Save Parameters");
        menuItem.setActionCommand("saveParams");
        menuItem.addActionListener(this);

        menu.add(menuItem);

        menuItem = new JMenuItem("Restore Parameters");
        menuItem.setActionCommand("restoreParams");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        tree.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent evt) {
                if (evt.isPopupTrigger()) {
                    menu.show(evt.getComponent(), evt.getX(), evt.getY());
                }
            }

            public void mouseReleased(MouseEvent evt) {
                if (evt.isPopupTrigger()) {
                    menu.show(evt.getComponent(), evt.getX(), evt.getY());
                }
            }
        });

    }

    private void createNodes(DefaultMutableTreeNode top) {
        DefaultMutableTreeNode evolutionaryPar = null;
        DefaultMutableTreeNode beingPar = null;
        DefaultMutableTreeNode filesPar = null;
        DefaultMutableTreeNode logPar = null;

        DefaultMutableTreeNode pr = null;

        beingPar = new DefaultMutableTreeNode("FSM");
        top.add(beingPar);

        pr = new DefaultMutableTreeNode(new Param("Type",
                EnvDescription.beingType.getName() + "   "));
        beingPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Number of states",
                EnvDescription.numberOfStates + "   "));
        beingPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Description",
                EnvDescription.description + "   "));
        beingPar.add(pr);

        evolutionaryPar = new DefaultMutableTreeNode("Evolution");
        top.add(evolutionaryPar);

        pr = new DefaultMutableTreeNode(new Param("Crossover",
                EnvDescription.CROSStype.getName()));
        evolutionaryPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Fitness fuction",
                EnvDescription.FFtype.getName()));
        evolutionaryPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Selection",
                EnvDescription.SELtype.getName()));
        evolutionaryPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Mutation",
                EnvDescription.MUTtype.getName()));
        evolutionaryPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Initialization",
                EnvDescription.generating.getName()));
        evolutionaryPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Size of population",
                EnvDescription.sizeOfPopulation + "    "));
        evolutionaryPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Number of generations",
                EnvDescription.numberOfGenerations + "   "));
        evolutionaryPar.add(pr);

        filesPar = new DefaultMutableTreeNode("Files");
        top.add(filesPar);

        pr = new DefaultMutableTreeNode(new Param("Training data",
                EnvDescription.dataFilename));
        filesPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Save result to",
                EnvDescription.Resfilename));
        filesPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Save FSM to",
                EnvDescription.FSMXMLfilename));
        filesPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Save parameters to",
                EnvDescription.ParamXMLfilename));
        filesPar.add(pr);

        logPar = new DefaultMutableTreeNode("Log");
        top.add(logPar);

        pr = new DefaultMutableTreeNode(new Param("Save Log to",
                EnvDescription.LOGfilename));
        logPar.add(pr);

        pr = new DefaultMutableTreeNode(new Param("Log ON/OFF",
                EnvDescription.loglevel.getName()));
        logPar.add(pr);

    }

    /** Required by TreeSelectionListener interface. */
    public void valueChanged(TreeSelectionEvent e) {
    }

    public void actionPerformed(ActionEvent e) {
        if ("saveParams".equals(e.getActionCommand())) { // new
            ParameterXMLWriter.writeParameters();
        }

    }

}

class Param {
    public String namePar;

    public String valuePar;

    public Param(String name, String value) {
        namePar = name;
        valuePar = value;

    }

    public String toString() {
        return namePar + ": " + valuePar;
    }
}

class DCMouseListener extends MouseAdapter {
    static JFileChooser fc = new JFileChooser(".");

    public void mouseClicked(MouseEvent evt) {
        JTree jt = (JTree) evt.getSource();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) jt
                .getLastSelectedPathComponent();
        if (node != null) {
            Object nodeInfo = node.getUserObject();
            if (evt.getClickCount() == 2) {

                if (node.isLeaf()) {
                    Param p = (Param) nodeInfo;
                    String s = p.namePar;

                    if (s == "Save parameters to") {
                        int returnVal = fc.showDialog(WMain.DMain,
                                "Choose file to save parameters");
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                            File file = fc.getSelectedFile();
                            EnvDescription.ParamXMLfilename = file.getName();
                            p.valuePar = EnvDescription.ParamXMLfilename;
                        }
                    } else if (s == "Save Log to") {
                        int returnVal = fc.showDialog(WMain.DMain,
                                "Choose file to save log");
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                            File file = fc.getSelectedFile();
                            EnvDescription.LOGfilename = file.getName();
                            p.valuePar = EnvDescription.LOGfilename;
                            Enviroment.defineLog();
                        }
                    } else if (s == "Save FSM to") {
                        int returnVal = fc.showDialog(WMain.DMain,
                                "Choose file to save FSM");
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                            File file = fc.getSelectedFile();
                            EnvDescription.FSMXMLfilename = file.getName();
                            p.valuePar = EnvDescription.FSMXMLfilename;
                        }

                    } else if (s == "Save result to") {
                        int returnVal = fc.showDialog(WMain.DMain,
                                "Choose file to save results");
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                            File file = fc.getSelectedFile();
                            EnvDescription.Resfilename = file.getName();
                            EnvDescription.resFile = file;
                            p.valuePar = EnvDescription.Resfilename;
                        }

                    } else if (s == "Training data") {
                        int returnVal = fc.showDialog(WMain.DMain,
                                "Open file with Training data");
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                            File file = fc.getSelectedFile();
                            EnvDescription.dataFilename = file.getName();
                            EnvDescription.dataFile = file;
                            p.valuePar = EnvDescription.dataFilename;

                        }

                    } else if (s == "Number of states") {
                        String input;
                        int inp = 0;

                        boolean correct = false;
                        while (!correct) {
                            input = JOptionPane
                                    .showInputDialog("Number of states:");
                            if ((input == null)) {
                                correct = true;
                                break;
                            }
                            if ((input.length() > 0)) {
                                inp = Integer.parseInt(input);
                                if (inp >= 1) {
                                    correct = true;
                                    EnvDescription.numberOfStates = inp;
                                    p.valuePar = EnvDescription.numberOfStates
                                            + "";
                                }
                            }

                        }

                    } else if (s == "Size of population") {
                        String input;
                        int inp = 0;

                        boolean correct = false;
                        while (!correct) {
                            input = JOptionPane
                                    .showInputDialog("Size of population:");
                            if ((input == null)) {
                                correct = true;
                                break;
                            }
                            if ((input.length() > 0)) {
                                inp = Integer.parseInt(input);
                                if ((inp >= 1) && (inp <= 1000)) {
                                    correct = true;
                                    EnvDescription.sizeOfPopulation = inp;
                                    p.valuePar = EnvDescription.sizeOfPopulation
                                            + "";
                                }
                            }

                        }

                    } else if (s == "Description") {
                        String input;

                        input = JOptionPane.showInputDialog("Description:");

                        EnvDescription.description = input;
                        p.valuePar = EnvDescription.description + "";

                    } else if (s == "Number of generations") {
                        String input;
                        int inp = 0;

                        boolean correct = false;
                        while (!correct) {
                            input = JOptionPane
                                    .showInputDialog("Number of generations:");
                            if ((input == null)) {
                                correct = true;
                                break;
                            }
                            if ((input.length() > 0)) {
                                inp = Integer.parseInt(input);
                                if ((inp >= 10) && (inp <= 5000)) {
                                    correct = true;
                                    EnvDescription.numberOfGenerations = inp;
                                    p.valuePar = EnvDescription.numberOfGenerations
                                            + "";
                                }
                            }

                        }

                    } else if (s == "Type") {
                        Object[] possibilities = {
                                Parameter.MEALY_MACHINE_FIXED.getName(),
                                Parameter.MOORE_MACHINE_FIXED.getName(),
                                Parameter.MOORE_MACHINE_MAX.getName() };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Choose FSM type", "Customized Dialog",
                                JOptionPane.PLAIN_MESSAGE, null, possibilities,
                                "FSM Type");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == Parameter.MEALY_MACHINE_FIXED
                                    .getName()) {
                                EnvDescription.beingType = Parameter.MEALY_MACHINE_FIXED;
                                p.valuePar = EnvDescription.beingType.getName();
                            } else if (input == Parameter.MOORE_MACHINE_FIXED
                                    .getName()) {
                                EnvDescription.beingType = Parameter.MOORE_MACHINE_FIXED;
                                p.valuePar = EnvDescription.beingType.getName();
                            } else if (input == Parameter.MOORE_MACHINE_MAX
                                    .getName()) {
                                EnvDescription.beingType = Parameter.MOORE_MACHINE_MAX;
                                p.valuePar = EnvDescription.beingType.getName();
                            }

                            return;
                        }

                    } else if (s == "Crossover") {
                        Object[] possibilities = {
                                Parameter.ONE_POINT_CROSSOVER.getName(),
                                Parameter.TWO_POINT_CROSSOVER.getName() };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Choose Crossover type",
                                "Customized Dialog", JOptionPane.PLAIN_MESSAGE,
                                null, possibilities, "Crossover Type");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == Parameter.ONE_POINT_CROSSOVER
                                    .getName()) {
                                EnvDescription.CROSStype = Parameter.ONE_POINT_CROSSOVER;
                                p.valuePar = EnvDescription.CROSStype.getName();
                            } else if (input == Parameter.TWO_POINT_CROSSOVER
                                    .getName()) {
                                EnvDescription.CROSStype = Parameter.TWO_POINT_CROSSOVER;
                                p.valuePar = EnvDescription.CROSStype.getName();
                            }

                            return;
                        }

                    } else if (s == "Fitness fuction") {
                        Object[] possibilities = {
                                Parameter.HAMMING_DISTANCE.getName(),
                                Parameter.MAX_PREFIX.getName() };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Choose Fitness function",
                                "Customized Dialog", JOptionPane.PLAIN_MESSAGE,
                                null, possibilities, "Fitness function");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == Parameter.HAMMING_DISTANCE.getName()) {
                                EnvDescription.FFtype = Parameter.HAMMING_DISTANCE;
                                p.valuePar = EnvDescription.FFtype.getName();

                            } else if (input == Parameter.MAX_PREFIX.getName()) {
                                EnvDescription.FFtype = Parameter.MAX_PREFIX;
                                p.valuePar = EnvDescription.FFtype.getName();
                            }

                            return;
                        }

                    } else if (s == "Selection") {
                        Object[] possibilities = { Parameter.ROULETTE_WHEEL_SELECTION
                                .getName() };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Choose Selection type",
                                "Customized Dialog", JOptionPane.PLAIN_MESSAGE,
                                null, possibilities, "Selection");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == Parameter.ROULETTE_WHEEL_SELECTION
                                    .getName()) {
                                EnvDescription.SELtype = Parameter.ROULETTE_WHEEL_SELECTION;
                                p.valuePar = EnvDescription.SELtype.getName();

                            }

                            return;
                        }

                    } else if (s == "Mutation") {
                        Object[] possibilities = {
                                Parameter.MUTATION.getName(),
                                Parameter.INVERSION.getName() };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Choose Mutation type",
                                "Customized Dialog", JOptionPane.PLAIN_MESSAGE,
                                null, possibilities, "Mutation");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == Parameter.MUTATION.getName()) {
                                EnvDescription.MUTtype = Parameter.MUTATION;
                                p.valuePar = EnvDescription.MUTtype.getName();

                            } else if (input == Parameter.INVERSION.getName()) {
                                EnvDescription.MUTtype = Parameter.INVERSION;
                                p.valuePar = EnvDescription.MUTtype.getName();
                            }

                            return;
                        }

                    } else if (s == "Initialization") {
                        Object[] possibilities = {
                                Parameter.GENERATING_BIN.getName(),
                                Parameter.GENERATING_DEC.getName() };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Choose Mutation type",
                                "Customized Dialog", JOptionPane.PLAIN_MESSAGE,
                                null, possibilities, "Mutation");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == Parameter.GENERATING_BIN.getName()) {
                                EnvDescription.generating = Parameter.GENERATING_BIN;
                                p.valuePar = EnvDescription.generating
                                        .getName();

                            } else if (input == Parameter.GENERATING_DEC
                                    .getName()) {
                                EnvDescription.generating = Parameter.GENERATING_DEC;
                                p.valuePar = EnvDescription.generating
                                        .getName();
                            }

                            return;
                        }
                    } else if (s == "Log ON/OFF") {
                        Object[] possibilities = { "ON", "OFF" };
                        String input = (String) JOptionPane.showInputDialog(
                                null, "Logging ON/OFF", "Customized Dialog",
                                JOptionPane.PLAIN_MESSAGE, null, possibilities,
                                "Logging ON/OFF");
                        if ((input != null) && (input.length() > 0)) {
                            if (input == "ON") {
                                EnvDescription.loglevel = Level.ALL;
                                p.valuePar = EnvDescription.loglevel.getName();

                            } else if (input == "OFF") {
                                EnvDescription.loglevel = Level.OFF;
                                p.valuePar = EnvDescription.loglevel.getName();
                            }

                            return;
                        }
                    }

                }
            }
        }
    }
}
